package cn.com.basic.framework.datahub;

import cn.hutool.core.lang.Assert;
import com.aliyun.datahub.client.DatahubClient;
import com.aliyun.datahub.client.DatahubClientBuilder;
import com.aliyun.datahub.client.auth.AliyunAccount;
import com.aliyun.datahub.client.common.DatahubConfig;
import com.aliyun.datahub.client.http.HttpConfig;
import com.aliyun.datahub.client.model.*;

/**
 * @author
 */
public class DatahubManager {

    /**
     * datahub端点
     */
    private String endpoint;
    /**
     * 阿里云账号 access key id
     */
    private String accessId;
    /**
     * 阿里云账号 access key secret
     */
    private String accessKey;

    /**
     * 是否采用二进制传输，服务端从2.12版本开始支持,之前版本需设置为false，
     * 专有云使用时出现错误’Parse body failed, Offset: 0’
     * 尝试设置为false
     */
    private boolean enableBinary;

    /**
     * Socket读写超时时间，默认10s
     */
    private int readTimeout;

    /**
     * TCP连接超时时间，默认10s
     */
    private int connTimeout;

    /**
     * 是否打印请求日志信息，默认false
     */
    private boolean debugRequest;

    private DatahubManager() {
        this.enableBinary = false;
        this.readTimeout = 10000;
        this.connTimeout = 10000;
        this.debugRequest = false;
    }

    private DatahubClient client;

    /**
     * 初始化客户端
     *
     * @return {@link DatahubClient}
     */
    public DatahubClient newClient() {
        if (this.client != null) {
            return client;
        }

        Assert.notBlank(accessId, "accessId 不能为 {}", accessId);
        Assert.notBlank(accessKey, "accessKey 不能为 {}", accessKey);
        Assert.notBlank(endpoint, "endpoint 不能为 {}", endpoint);

        client = DatahubClientBuilder.newBuilder()
                .setDatahubConfig(new DatahubConfig(endpoint, new AliyunAccount(accessId, accessKey), enableBinary))
                .setHttpConfig(new HttpConfig()
                        .setReadTimeout(readTimeout)
                        .setConnTimeout(connTimeout)
                        .setDebugRequest(debugRequest))
                .build();
        return client;
    }

    /**
     * 新增项目空间
     *
     * @param project 项目空间名称
     * @param comment 注释
     * @return {@link CreateProjectResult}
     */
    public CreateProjectResult createProject(String project, String comment) {
        return newClient().createProject(project, comment);
    }

    /**
     * 删除项目空间
     *
     * @param project 项目空间名称
     * @return {@link DeleteProjectResult}
     */
    public DeleteProjectResult deleteProject(String project) {
        return newClient().deleteProject(project);
    }


    /**
     * 更新项目空间注释
     *
     * @param project 项目空间名称
     * @param comment 注释
     */
    public void updateProject(String project, String comment) {
        newClient().updateProject(project, comment);
    }

    /**
     * 查看所有项目名称
     *
     * @return {@link ListProjectResult}
     */
    public ListProjectResult listProjects() {
        return newClient().listProject();
    }

    /**
     * 查看某个项目空间基本信息
     *
     * @param project 项目空间名称
     * @return {@link GetProjectResult}
     */
    public GetProjectResult getProject(String project) {
        Assert.notBlank(project);
        return newClient().getProject(project);
    }


    /**
     * 创建Topic
     *
     * @param project      项目空间名称
     * @param topic        topic名称
     * @param shardCnt     通道数
     * @param lifeCycle    生命周期
     * @param recordType   记录类型
     * @param recordSchema 记录模型
     * @param comment      注释
     * @return {@link CreateTopicResult}
     */
    public CreateTopicResult createTopic(String project, String topic, int shardCnt, int lifeCycle, RecordType recordType, RecordSchema recordSchema, String comment) {
        Assert.notBlank(project);
        Assert.notBlank(topic);
        Assert.isTrue(shardCnt > 0);
        Assert.isTrue(lifeCycle > 0);
        return newClient().createTopic(project, topic, shardCnt, lifeCycle, recordType, recordSchema, comment);
    }

    /**
     * 删除Topic
     *
     * @param project 项目空间名称
     * @param topic   topic名称
     * @return {@link DeleteTopicResult}
     */
    public DeleteTopicResult deleteTopic(String project, String topic) {
        Assert.notBlank(project);
        Assert.notBlank(topic);
        return newClient().deleteTopic(project, topic);
    }

    /**
     * 修改Topic 目前只支持修改注释
     *
     * @param project 项目空间名称
     * @param topic   topic名称
     * @param comment 注释
     * @return {@link UpdateTopicResult}
     */
    public UpdateTopicResult updateTopic(String project, String topic, String comment) {
        Assert.notBlank(project);
        Assert.notBlank(topic);
        return newClient().updateTopic(project, topic, comment);
    }

    /**
     * 获得Topic详情
     *
     * @param project 项目空间名称
     * @param topic   topic名称
     * @return {@link GetTopicResult}
     */
    public GetTopicResult getTopic(String project, String topic) {
        Assert.notBlank(project);
        Assert.notBlank(topic);
        return newClient().getTopic(project, topic);
    }

    /**
     * 创建订阅号
     *
     * @param project 项目空间名称
     * @param topic   topic名称
     * @param comment 订阅号注释
     * @return {@link CreateSubscriptionResult}
     */
    public CreateSubscriptionResult createSubscription(String project, String topic, String comment) {
        Assert.notBlank(project);
        Assert.notBlank(topic);
        Assert.notBlank(comment);
        return newClient().createSubscription(project, topic, comment);
    }

    public static DatahubManager newInstance() {
        return new DatahubManager();
    }

    public DatahubManager setAccessId(String accessId) {
        this.accessId = accessId;
        return this;
    }

    public DatahubManager setEndpoint(String endpoint) {
        this.endpoint = endpoint;
        return this;
    }

    public DatahubManager setAccessKey(String accessKey) {
        this.accessKey = accessKey;
        return this;
    }

    public DatahubManager setEnableBinary(boolean enableBinary) {
        this.enableBinary = enableBinary;
        return this;
    }

    public DatahubManager setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
        return this;
    }

    public DatahubManager setConnTimeout(int connTimeout) {
        this.connTimeout = connTimeout;
        return this;
    }

    public DatahubManager setDebugRequest(boolean debugRequest) {
        this.debugRequest = debugRequest;
        return this;
    }
}